<?php
namespace App\Backend\Service;
use App\Libs\QiniuLibrary;
use App\Libs\CompressLibrary;
use App\Models\SiteConfig;
use App\Models\File;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use App\Exceptions\InvalidRequestException;
use Illuminate\Support\Facades\Config;
use OSS\OssClient;
use OSS\Core\OssException;


class FileUploadService extends BaseService
{
    private $max_size   = '50000000'; //设置上传文件的大小，此为2M
    private $rand_name   = true;   //是否采用随机命名
    private $allow_type  = [];  //允许上传的文件扩展名
    private $error     = 0;     //错误代号
    private $msg      = '';    //信息
    private $new_name   = '';    //上传后的文件名
    private $save_path   = '';    //文件保存路径
    private $uploaded   = '';    //路径.文件名
    private $file     = '';    //等待上传的文件
    private $file_type   = [];  //文件类型
    private $file_ext   = '';    //上传文件的扩展名
    private $file_name   = '';    //文件原名称
    private $file_size   = 0;     //文件大小
    private $file_tmp_name = '';    //文件临时名称
    private $img_arr=['jpg', 'jpeg', 'png']; //图片
    private $file_arr=['apk']; //文件
    private $type;//检测上传文件类型  图片还是文件
    private $file_url;
    /**
     * 构造函数，初始化
     * @param string $rand_name 是否随机命名
     * @param string $save_path 文件保存路径
     * @param string $allow_type 允许上传类型
        $allow_type可为数组  array('jpg', 'jpeg', 'png', 'gif');
        $allow_type可为字符串 'jpg|jpeg|png|gif';中间可用' ', ',', ';', '|'分割
     */
    public function __construct($rand_name=true, $save_path='./upload/',$allow_type='')
    {
        //parent ::__construct();
        $path = storage_path();
        $this->file_url=$save_path;
        $this->rand_name = $rand_name;
        $this->save_path =str_replace('\\', '/',$path.$save_path);
       // dd($this->save_path);exit;

        //var_dump($this->save_path);exit;
        $this->allow_type = $this->get_allow_type($allow_type);
    }

    /* 检查是否有存放上传文件的目录 */
    private function checkFilePath() 
    {
        if(empty($this->save_path)){
            $this->msg = '保存文件地址不能为空';
            return false;
        }

        if (!file_exists($this->save_path) || !is_writable($this->save_path)) 
        {
            if (!mkdir($this->save_path, 0777,true))
            {
                //die('2');
                $this->msg = '创建文件目录失败';
                return false;
            }
        }
        //die('3');
        return true;
    }
    #文件压缩检测有些不允许压缩
    private static function checkCanComression($request)
    {

        //不允许压缩的类别
        $arr = [];

        return true;
        
    }
    public function config_info(){
        $info = SiteConfig::getInfo(SiteConfig::SITE_CONFIG['UPLOAD']);
        if(empty($info)){
            $this->msg = '请配置附件上传信息';
            return false;
        }
        $content = json_decode($info->content, true);
        if(empty($content) || empty($content['storage_type'])) {
            $this->msg = '请配置附件上传信息';
            return false;
        }
        #上传到本地  storage_type=1
        if($content['storage_type'] == '1'){
            return '1';
        }else{
            //7牛云
            return '2';
        }

       // dd($content['is_compression']);exit;

    }
    /**
     * 上传文件
     * 在上传文件前要做的工作
     * (1) 获取文件所有信息
     * (2) 判断上传文件是否合法
     * (3) 设置文件存放路径
     * (4) 是否重命名
     * (5) 上传完成
     * @param array $file 上传文件
     *     $file须包含$file['name'], $file['size'], $file['error'], $file['tmp_name']
     */
    public function upload_file($file)
    {
        #获取配置信息
        $res=$this->config_info();
        $this->checkFilePath();
        $this->file_name   = $file['name'];
        $this->file_size   = $file['size'];
        $this->error     = $file['error'];
        $this->file_tmp_name = $file['tmp_name'];
      
        $this->ext = $this->get_file_type($this->file_name);
      
        switch($this->error){
            case '0': 
                $this->msg = '';
                break;
            case '1':
                $this->msg = '超出了php.ini中文件大小';
                break;
            case '2': 
                $this->msg = '超出了MAX_FILE_SIZE的文件大小';
                break;
            case '3':
                $this->msg = '文件被部分上传';
                break;
            case '4': 
                $this->msg = '没有文件上传'; 
            break;
            case '5':
                $this->msg = '文件大小为0';
                break;
            default: 
                $this->msg = '上传失败'; 
                break;
        }
        if($this->error==0 && is_uploaded_file($this->file_tmp_name))
        {
            //检测文件类型
            if(in_array($this->ext, $this->allow_type)==false)
            {
              $this->msg = '文件类型不正确';
              return false;
            }
            //检测文件大小
            if($this->file_size > $this->max_size)
            {
              $this->msg = '文件过大1';
              return false;
            }
        }
        $this->set_file_name();
        $this->uploaded = $this->save_path.$this->new_name;
        $this->file_url=$this->file_url.$this->new_name;
        //dd($this->file_url);exit;
        if(move_uploaded_file($this->file_tmp_name, $this->uploaded))
        {
            $this->msg = '文件上传成功';
            $this->ys_img();
            if($res=='2'){
                $this->yun_up();
            }
            return true;
        }else{
            $this->msg = '文件上传失败';
            return false;
        }
    }
   
    public function ys_img()
    {
        if($this->type=='pic'){
            $file_url = $this->file_url;
            $storage_path = storage_path();
            $file_url=$storage_path.$file_url;
           // dd($file_url);
            #压缩图片
            (new CompressLibrary($file_url))->compressImg();
        }
    }
    public function getnewpath($oldpath){
      $url = str_replace('\\','/',$oldpath);
      return $url;
    }

    //本地上传-返回值
    public function return_upload_image($request,$data=[])
    {
        $savename=$data['savename'];
        $rand = rand(1000,9999);
        $timestamp = time();
        //截取文件后缀名如 (.jpg)
        $format = strrchr($savename,'.');
        if (config()->has('oss')) {

            $oss = config('oss');
        }else{
            $this->error("oss 文件不存在");
        }
        $accessKeyId =$oss['access_key_id'];
        $accessKeySecret = $oss['access_key_secret'];
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        $endpoint = $oss['endpoint'];
        // 设置存储空间名称。
        $bucket= $oss['bucket'];
        //dd($oss);
   
        try{
            $ossClient = new OssClient($accessKeyId,$accessKeySecret,$endpoint);
            #判断bucketname是否存在，不存在就去创建
            if( !$ossClient->doesBucketExist($bucket)){
                $ossClient->createBucket($bucket);
            }
            $category=$bucket;
            $object = $category.'/uploads/'.sha1(date('YmdHis', time()) . uniqid()) . $format;
            //dd($object);
            $object = str_replace("\\","/",$object);
            $savename = str_replace("\\","/",$savename);
            if (!file_exists($savename)) {
               return "{$savename}本地文件不存在";
            }
            $result = $ossClient->uploadFile($bucket, $object,$savename);
            if(!$result){

                return "oss图片上传失败";
             }else{
                $this->uploaded=$result['info']['url'];
                return($this->uploaded);
            }
        } catch(OssException $e) {
            return "{$e->getMessage()}";
        }

    }

    //本地图片-上传
    public function upload_image($request,$data=[])
    {
        $savename=$data['savename'];
        $rand = rand(1000,9999);
        $timestamp = time();
        //截取文件后缀名如 (.jpg)
        $format = strrchr($savename,'.');
        if (config()->has('oss')) {
            $oss = config('oss');
        }else{
            $this->error("oss 文件不存在");
        }
        $accessKeyId =$oss['access_key_id'];
        $accessKeySecret = $oss['access_key_secret'];
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        $endpoint = $oss['endpoint'];
        // 设置存储空间名称。
        $bucket= $oss['bucket'];
        //dd($oss);
   
        try{
            $ossClient = new OssClient($accessKeyId,$accessKeySecret,$endpoint);
            #判断bucketname是否存在，不存在就去创建
            if( !$ossClient->doesBucketExist($bucket)){
                $ossClient->createBucket($bucket);
            }
            $category=$bucket;
            $object = $category.'/uploads/'.sha1(date('YmdHis', time()) . uniqid()) . $format;
            //dd($object);
            $object = str_replace("\\","/",$object);
            $savename = str_replace("\\","/",$savename);
            if (!file_exists($savename)) {
               $this->error('本地文件不存在');
            }
            $result = $ossClient->uploadFile($bucket, $object,$savename);
            if(!$result){

                $this->error("上传失败");
             }else{
                $this->uploaded=$result['info']['url'];
                $this->success($this->uploaded);
            }
        } catch(OssException $e) {
            $this->error($e->getMessage());
        }
    }
    public function yun_up()
    {
       /* require_once "../vendor/oss/OssClient.php";
        require_once "../vendor/oss/Core/OssException.php";
        require_once "../vendor/autoloadoss.php"; */
        $rand = rand(1000,9999);
        $storage_path = storage_path();
        $timestamp = time();
        $file_url = $this->file_url;
        //截取文件后缀名如 (.jpg)
        $format = strrchr($file_url, '.');
        //dd($file_url);
        if (config()->has('oss')) {
            $oss = config('oss');
        }else{
            $this->error("oss 文件不存在");
        }
        $accessKeyId =$oss['access_key_id'];
        $accessKeySecret = $oss['access_key_secret'];
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        $endpoint = $oss['endpoint'];
        // 设置存储空间名称。
        $bucket= $oss['bucket'];
   
        $savename=$storage_path.$file_url;
        //dd($savename);
        //$filePath = $files['tmp_name'];
        $savename=$this->getnewpath($savename);


       // dump($oss);exit;
        try{
            $ossClient = new OssClient($accessKeyId, $accessKeySecret,$endpoint);
            #判断bucketname是否存在，不存在就去创建
            if( !$ossClient->doesBucketExist($bucket)){
                $ossClient->createBucket($bucket);
            }
            $category=$bucket;
            $object = $category.'/uploads/'.sha1(date('YmdHis', time()) . uniqid()) . $format;
            //dd($object);
            $object = str_replace("\\","/",$object);
            $savename = str_replace("\\","/",$savename);
            if (!file_exists($savename)) {
               $this->result('本地文件不存在');
            }
            $result = $ossClient->uploadFile($bucket, $object,$savename);
            if(!$result){
                $this->msg = '上传失败';
                return false;
             }else{
                
                $this->uploaded=$result['info']['url'];
                $this->file_url=$result['info']['url'];
                $this->msg = '上传成功';
                return true;
            }
        } catch(OssException $e) {
            $this->msg = $e->getMessage();
            return false;
        }
    }
    #上传到云存储
    public function yun_up2()
    {
        $rand = rand(1000,9999);
        $storage_path = storage_path();
        $timestamp = time();
        $file_url = $this->file_url;
        $key = 'client-file/pic/sls-'.$rand.$timestamp.'.'.$this->ext;
        $file_info = (new QiniuLibrary)->upload($storage_path.$file_url, $key);
        if($file_info['code']=='1'){
            $this->uploaded=$file_info['url'];
            $this->file_url=$file_info['url'];
            $this->msg = '上传成功';
            $this->insertdb();
            return true;
        }else{
            $this->msg = '上传失败';
            return false;
        }

    }
    public function insertdb(){
        $data = [
            'file_ext' =>$this->ext,
            'file_name' =>$this->file_name,
            'file_size' =>$this->file_size,
            'url'=>$this->file_url,
            'status'=>'1',
            'uploader'=>$this->userId,
            'create_time'=>time(),
            'update_time'=>time(),

        ];
        $res=File::insert($data);
    }
    /**
    * 设置上传后的文件名
    * 当前的毫秒数和原扩展名为新文件名
    */
    public function set_file_name()
    {
      if($this->rand_name==true)
      {
        $a = explode(' ', microtime());
        $t = $a[1].($a[0]*1000000);
        $this->new_name = $t.'.'.($this->ext);
      }else{
        $this->new_name = $this->file_name;
      }
    }
    
    /**
    * 获取上传文件类型
    * @param string $filename 目标文件
    * @return string $ext 文件类型
    */
    public function get_file_type($filename)
    {
        $ext = pathinfo($filename, PATHINFO_EXTENSION);
        if(in_array($ext,$this->img_arr)){
            $this->type='pic';
        }else{
            $this->type='file';
        }

        if ($this->type == 'file') {
            $this->max_size = Config::get('upload.file_upload_max');
        }else{
            $this->max_size = Config::get('upload.pic_upload_max');
        }
        return $ext;
    }
    
    /**
     * 获取可上传文件的类型
     */
    public function get_allow_type($allow_type)
    {
      $s = [];
      if(is_array($allow_type))
      {
        foreach($allow_type as $value)
        {
          $s[] = $value;
        }
      }else{
        $s = preg_split("/[\s,|;]+/", $allow_type);
      }
      return $s;
    }
    
    //获取错误信息
    public function get_msg()
    {
      return $this->msg;
    }
    //获取图片相对路径地址
    public function get_imgurl()
    {
        return $this->file_url;
    }
    //获取图片绝对路径地址
    public function get_imgurl2()
    {
        return $this->uploaded;
    }

    // 获取文件类型  图片还是文件
    public function get_type(){
        return $this->type;
    }


  }
?>
